<?php

class gameMaster
{
        private $log;
        
        public function __construct($loger)
	{
		$this->log=$loger;
	}
        
        public function AddLog($sMessage,$title='gameMaster',$level=1)
        {
           $this->log->logSection($title,$sMessage);
        }
        
        public function IsNeedRandomize($oTournament)
        {
            $this->AddLog('IsNeedRandomize:check');
            if(!GameMatchPeer::getMatchCount($oTournament->getId()))
            {
                $this->AddLog('IsNeedRandomize:null');
                return true;
            }else{
                $this->AddLog('IsNeedRandomize:not null');
                return GameMatchPeer::getStartMatchCount($oTournament->getId())?false:true;
            }
            return false;
        }
        
        
        public function getGameNode($tree)
        {
            $this->AddLog('getGameNode: getFirstNode'.$tree->getFirstNode()); 
            $node=$tree->getNode($tree->getFirstNode()); 
            $this->AddLog('getGameNode-getNode: '.  var_dump($node)); 
            
            while($node->getType()==gameRules::$TN_NATURE)
            {         
                $mode_action=$node->getActions();
                $next_node_id=$mode_action[$node->getRandomId()][2];
                $this->AddLog('getGameNode: $next_node_id'.$next_node_id);
                $node=$tree->getNode($next_node_id);
                $this->AddLog('getGameNode-getNodeNext: '.  var_dump($node));
            }
            
            return $node->getId();
        }


        private function playerShereAllEven($aPlayers,$oTournament,$iRound=1)
        {
                $iPlayersCount=count($aPlayers); 
                $iIdTmpPlayer=array();
                $iMaxGame=$iPlayersCount-1;
                
                $data_node=  unserialize($oTournament->getRules()->getData());
                
                foreach($aPlayers as $oPlayer)
                {
                        $iIdTmpPlayer[]=$oPlayer->getId();
                }
                
                $iIdPlayer=array();
                
                $iStartShift=($iRound%$iMaxGame)?($iRound%$iMaxGame):$iMaxGame;
                
                $this->AddLog('playerShereAll:$iStartShift: '.  $iStartShift);
                $this->AddLog('playerShereAll:$iRound: '.  ($iRound));
                $this->AddLog('playerShereAll:$iMaxGame: '.  $iMaxGame);
                $this->AddLog('playerShereAll:$iRound: '.  ($iRound));
                $this->AddLog('playerShereAll:$iRound%($iMaxGame): '.  ($iRound%($iMaxGame)));
                
                
                $iIdPlayer[]=$iIdTmpPlayer[0];
                
                for($i=$iStartShift;$i<$iPlayersCount;$i++)
                {
                    $iIdPlayer[]=$iIdTmpPlayer[$i];
                }
                                
                for($i=1;$i<$iStartShift;$i++)
                {
                    $iIdPlayer[]=$iIdTmpPlayer[$i];
                }
                
                $this->AddLog('playerShereAll:gracze: '.  var_dump($iIdPlayer));
                
                $iDivPlayersCount=$iPlayersCount/2;
                
                for($i=0;$i<$iDivPlayersCount;$i++)
                {
                   /* $iIdPlayer[$i]->setStatus(ActivPlayer::$ACTION_PLAYING);
                    $iIdPlayer[$i]->save();
                    
                    $iIdPlayer[$iPlayersCount-$i-1]->setStatus(ActivPlayer::$ACTION_PLAYING);
                    $iIdPlayer[$iPlayersCount-$i-1]->save();
                  */  
                    $oMatch=new GameMatch();
                    $oMatch->setFirstPlayerId($iIdPlayer[$i]);
                    $oMatch->setSecondPlayerId($iIdPlayer[$iPlayersCount-$i-1]);
                    $oMatch->setTournamentId($oTournament->getId());
                    $oMatch->setRoundId($iRound);
                    $oMatch->save();
                                    
                    $gm=new Game();
                    $gm->setMatchId($oMatch->getId());
                    $gm->setStatus(Game::$GAME_STATUS_START);
                    $gm->setSwitches(false);
                    if($data_node->getType()==gameRules::$RT_TREE)
                            $gm->setNode ($this->getGameNode($data_node));
                    $gm->save();
                    
                    $this->AddLog('playerShereAll: '.$iIdPlayer[$i].' vs '.$iIdPlayer[$iPlayersCount-$i-1]);
                }
                
                $c=new Criteria();
                $c->add(ActivPlayerPeer::ID,$iIdPlayer,  Criteria::IN);              
                $c->add(ActivPlayerPeer::STATUS,  ActivPlayer::$ACTION_PLAYING);              
                $this->AddLog('ActivPlayerPeer::doUpdate: '.ActivPlayerPeer::doUpdate($c)); 
                
        }        

        private function playerShereAllOdd($aPlayers,$oTournament,$iRound=1)
        {
                $this->AddLog('playerShereOdd:round: '. $iRound);
            
                $iPlayersCount=count($aPlayers);    
                $iIdTmpPlayer=array();
                $iMaxGame=$iPlayersCount;
            
                $data_node=  unserialize($oTournament->getRules()->getData());
                
                foreach($aPlayers as $oPlayer)
		{
                    $iIdTmpPlayer[]=$oPlayer->getId();
		}                               
                
                $iIdPlayer=array();
                
                $this->AddLog('playerShereOdd:$iMaxGame: '.  $iMaxGame);
                
                $this->AddLog('playerShereOdd:$iRound: '.  $iRound);
                
                $iStartShift=($iRound%$iMaxGame)?($iRound%$iMaxGame):$iMaxGame;
                $iStartShift--;
                $this->AddLog('playerShereOdd:$iStartShift: '.  $iStartShift);
                
                for($i=$iStartShift;$i<$iPlayersCount;$i++)
                {
                    $iIdPlayer[]=$iIdTmpPlayer[$i];
                }
                                
                for($i=0;$i<$iStartShift;$i++)
                {
                    $iIdPlayer[]=$iIdTmpPlayer[$i];
                }
                
                $this->AddLog('playerShereOdd:gracze: '.  var_dump($iIdPlayer));
                
                $aPlayers[0]->setStatus(ActivPlayer::$ACTION_FREE);
                $aPlayers[0]->save();
                         
                $oMatch=new GameMatch();
                $oMatch->setFirstPlayerId($iIdPlayer[0]);
                $oMatch->setSecondPlayerId($iIdPlayer[0]);
                $oMatch->setTournamentId($oTournament->getId());
                $oMatch->setRoundId($iRound);
                $oMatch->setStatus(GameMatch::$GAMEMATCH_STATUS_ENDED);
                $oMatch->save();
                
                $this->AddLog('playerShereOdd:wyjebany: '.$iIdPlayer[0]);
                           
                
                $iDivPlayersCount=$iPlayersCount/2;
                
                for($i=1;$i<$iDivPlayersCount;$i++)
                {
                   /* $iIdPlayer[$i]->setStatus(ActivPlayer::$ACTION_PLAYING);
                    $iIdPlayer[$i]->save();
                    
                    $iIdPlayer[$iPlayersCount-$i]->setStatus(ActivPlayer::$ACTION_PLAYING);
                    $iIdPlayer[$iPlayersCount-$i]->save();
                  */
                    $oMatch=new GameMatch();
                    $oMatch->setFirstPlayerId($iIdPlayer[$i]);
                    $oMatch->setSecondPlayerId($iIdPlayer[$iPlayersCount-$i]);
                    $oMatch->setTournamentId($oTournament->getId());
                    $oMatch->setRoundId($iRound);
                    $oMatch->save();
                    
                    $gm=new Game();
                    $gm->setMatchId($oMatch->getId());
                    $gm->setStatus(Game::$GAME_STATUS_START);
                    $gm->setSwitches(false);
                    if($data_node->getType()==gameRules::$RT_TREE)
                            $gm->setNode ($this->getGameNode($data_node));
                    $gm->save();
                    
                    $this->AddLog('playerShereOdd: '.$iIdPlayer[$i].' vs '.$iIdPlayer[$iPlayersCount-$i]);
                }
                
                $c=new Criteria();
                $c->add(ActivPlayerPeer::ID,$iIdPlayer,  Criteria::IN);              
                $c->add(ActivPlayerPeer::STATUS,  ActivPlayer::$ACTION_PLAYING);              
                $this->AddLog('ActivPlayerPeer::doUpdate: '.ActivPlayerPeer::doUpdate($c)); 
        } 
        
        public function playerShereAll($oTournament,$iRound=1)
	{
		$aPlayers=ActivPlayerPeer::retrieveByTournament($oTournament->getId());
		$iPlayersCount=count($aPlayers);
		
                $this->AddLog('$iPlayersCount: '.$iPlayersCount);
                
                if($iPlayersCount<2)
                {
                    return $iPlayersCount;
                }
                
                if($iPlayersCount%2)
                {
                    $this->playerShereAllOdd($aPlayers,$oTournament,$iRound);                    
                }else{
                    $this->playerShereAllEven($aPlayers,$oTournament,$iRound);
                }
                
                return $iPlayersCount;
	}	
	
        private function selectSwissGroup($rank)
        {
            $groups=array();
            $key=  array_keys($rank);
            $iCount=count($key);
            $iCounter=0;
            
            for($i=0;$i<$iCount;$i++)
            {
                $groups[$iCounter]=array($key[$i]);
                for($j=$i+1;$j<$iCount;$j++)
                {
                    if($rank[$key[$i]]==$rank[$key[$j]])
                    {
                       $groups[$iCounter][]=$key[$j];
                       $i++;
                    }else{
                        if($j%2==1)
                        {
                            $groups[$iCounter][]=$key[$j];
                            $i++;
                        }
                        ++$iCounter;
                        break;                        
                    }
                }                
            }          
                       
            return $groups;
        }
        
        private function generateSwissMatch($group,$oTournament,$iRound)
        {
                $iPlayersCount=count($group);
                
                $data_node=  unserialize($oTournament->getRules()->getData());
                
                
		for ($i=0; $i<$iPlayersCount; $i++)
		{
			
                        if($iPlayersCount-$i!=2)
			{
				$oPlayer1=array_shift($group);
				$oPlayer2=array_shift($group);
				$oPlayer3=array_shift($group);
				$oPlayer4=array_shift($group);
				
                                
                               // $oPlayer1->setStatus(ActivPlayer::$ACTION_PLAYING);
                              //  $oPlayer1->save();

                              //  $oPlayer2->setStatus(ActivPlayer::$ACTION_PLAYING);
                              //  $oPlayer2->save();

                              //  $oPlayer3->setStatus(ActivPlayer::$ACTION_PLAYING);
                              //  $oPlayer3->save();

                              //  $oPlayer4->setStatus(ActivPlayer::$ACTION_PLAYING);
                              //  $oPlayer4->save();
                                
				$oMatch=new GameMatch();
				$oMatch->setFirstPlayerId($oPlayer1);
				$oMatch->setSecondPlayerId($oPlayer3);
				$oMatch->setTournamentId($oTournament->getId());
                                $oMatch->setRoundId($iRound);
				$oMatch->save();
				
                                $this->AddLog('playerShereSwiss:generateSwissMatch:'.$oPlayer1.' vs '.$oPlayer3);
                                
                                
                                $gm=new Game();
                                $gm->setMatchId($oMatch->getId());
                                $gm->setStatus(Game::$GAME_STATUS_START);
                                $gm->setSwitches(false);
                                if($data_node->getType()==gameRules::$RT_TREE)
                                    $gm->setNode ($this->getGameNode($data_node));
                                $gm->save();
                                
				$oMatch=new GameMatch();
				$oMatch->setFirstPlayerId($oPlayer2);
				$oMatch->setSecondPlayerId($oPlayer4);
				$oMatch->setTournamentId($oTournament->getId());
                                $oMatch->setRoundId($iRound);
				$oMatch->save();
				
                                $this->AddLog('playerShereSwiss:generateSwissMatch:'.$oPlayer2.' vs '.$oPlayer4);
                                $i+=4;
                                
                                $gm=new Game();
                                $gm->setMatchId($oMatch->getId());
                                $gm->setStatus(Game::$GAME_STATUS_START);
                                $gm->setSwitches(false);
                                if($data_node->getType()==gameRules::$RT_TREE)
                                    $gm->setNode ($this->getGameNode($data_node));
                                $gm->save();
				
			}else{
				$oPlayer1=array_shift($group);
				$oPlayer2=array_shift($group);
				
                                
                              //  $this->AddLog('playerShereSwiss:generateSwissMatch:'.var_dump($oPlayer1));
                                
                               // $oPlayer1->setStatus(ActivPlayer::$ACTION_PLAYING);
                               // $oPlayer1->save();

                               // $oPlayer2->setStatus(ActivPlayer::$ACTION_PLAYING);
                               // $oPlayer2->save();
                                
				$oMatch=new GameMatch();
				$oMatch->setFirstPlayerId($oPlayer2);
				$oMatch->setSecondPlayerId($oPlayer1);
				$oMatch->setTournamentId($oTournament->getId());
                                $oMatch->setRoundId($iRound);
				$oMatch->save();
				
                                $gm=new Game();
                                $gm->setMatchId($oMatch->getId());
                                $gm->setStatus(Game::$GAME_STATUS_START);
                                //$gm->setSwitches(false);
                                if($data_node->getType()==gameRules::$RT_TREE)
                                    $gm->setNode ($this->getGameNode($data_node));
                                $gm->save();
                                
                                
                                
                                $this->AddLog('playerShereSwiss:generateSwissMatch:'.$oPlayer1.' vs '.$oPlayer2);
                                
                                break;
			}
		}
        }

        public function playerShereSwiss($oTournament,$iRound=1)
	{
		if(!$oTournament->getAckRound())
                {
                    $this->AddLog('playerShereSwiss:getAckRound:0');
                    return $this->playerShereRandom($oTournament);
                }
                
                $aPlayers=ActivPlayerPeer::retrieveByTournament($oTournament->getId());		
		$iPlayersCount=count($aPlayers);
		
                $this->AddLog('playerShereSwiss:$iPlayersCount:'.$iPlayersCount);
                
		if($iPlayersCount%2)
		{
			
                        $key=array_rand($aPlayers,1);			
			//$aPlayers[$key]->setStatus(ActivPlayer::$ACTION_WIN);
                        $aPlayers[$key]->setStatus(ActivPlayer::$ACTION_FREE);
                        $aPlayers[$key]->save();
                        
                        $oMatch=new GameMatch();
                        $oMatch->setFirstPlayerId($aPlayers[$key]);
                        $oMatch->setSecondPlayerId($aPlayers[$key]);
                        $oMatch->setTournamentId($oTournament->getId());
                        $oMatch->setRoundId($iRound);
                        $oMatch->setStatus(GameMatch::$GAMEMATCH_STATUS_END);
                        $oMatch->setResult(GameMatch::$GAMEMATCH_RESULT_FIRST);
                        $oMatch->save();
                                
                        $gm=new Game();
                        $gm->setMatchId($oMatch->getId());
                        $gm->setStatus(Game::$GAME_STATUS_ENDED);
                        //$gm->setSwitches(false);
                        $gm->save();
                        
                        $pts=new Score();
                        $pts->setMatchId($oMatch->getId());
                        $pts->setGameId($gm->getId());
                        $pts->setScore($oTournament->getRules()->getFreepts());
                        $pts->save();
                        
                        
                        $this->AddLog('playerShereSwiss:$iPlayersCount%2:'.$aPlayers[$key]->getId());
			unset($aPlayers[$key]);
                        
		}
		
		$iPlayersCount--;
                
                $c = new Criteria();
                $c->add(GameMatchPeer::TOURNAMENT_ID,$oTournament->getId());
                $result=GameMatchPeer::doSelect($c);
                
                $all_match=array();
                
                foreach($result as $res)
                {
                    $all_match[]=$res->getId();
                }
                
                $this->AddLog('playerShereSwiss:$iPlayersCount%2:'.var_dump($all_match));
                                
                $c = new Criteria();
                $c->addSelectColumn(ScorePeer::PLAYER_ID);
                $c->addSelectColumn('SUM('.ScorePeer::BIG_SCORE.') as cnt');
                $c->add(ScorePeer::MATCH_ID,$all_match,Criteria::IN);                
                $c->addGroupByColumn(ScorePeer::PLAYER_ID);
                
                $mt=  unserialize($oTournament->getRules()->getData());
                
                if($mt->getWinPoints()==gameRules::$GW_Less)
                    $c->addAscendingOrderByColumn('cnt');
                else
                    $c->addDescendingOrderByColumn('cnt');
                
                $res=ScorePeer::doSelectStmt($c);
                
                $ranking=array();
                
                foreach ($res->fetchAll() as $node)
                {
                    $ranking[$node[0]] = $node[1];
                    $this->AddLog('playerShereSwiss:fetchAll:'.$node[0].'<=>'.$node[1]);
                }
                
                $groups=$this->selectSwissGroup($ranking);
                
                $this->AddLog('playerShereSwiss:selectSwissGroup:'.var_dump($groups));
                
                $all_new_players=array();
                
		foreach($groups as $group)
                {
                   $this->AddLog('playerShereSwiss:selectSwissGroup:groups');
                   $this->generateSwissMatch($group,$oTournament,$iRound);
                   $all_new_players=array_merge($all_new_players,$group);
                }
                
                $c=new Criteria();
                $c->add(ActivPlayerPeer::ID,$all_new_players,  Criteria::IN);              
                $c->add(ActivPlayerPeer::STATUS,  ActivPlayer::$ACTION_PLAYING);              
                $this->AddLog('ActivPlayerPeer::doUpdate: '.ActivPlayerPeer::doUpdate($c)); 
                
	}
	
	public function playerShereRandom($oTournament,$iRound=1)
	{
		$aPlayers=ActivPlayerPeer::retrieveByTournament($oTournament->getId());		
		$iPlayersCount=count($aPlayers);
               
                $data_node=  unserialize($oTournament->getRules()->getData());
                
                if($iPlayersCount%2)
		{		
			$key=array_rand($aPlayers,1);			
			$aPlayers[$key]->setStatus(ActivPlayer::$ACTION_FREE);
                        $aPlayers[$key]->save();
			$iPlayersCount--;
                        
                        $oMatch=new GameMatch();
			$oMatch->setFirstPlayerId($aPlayers[$key]);
			$oMatch->setSecondPlayerId($aPlayers[$key]);
                        $oMatch->setRoundId($iRound);
                        $oMatch->setStatus(GameMatch::$GAMEMATCH_STATUS_END);
			$oMatch->setTournamentId($oTournament->getId());
                        $oMatch->setResult(GameMatch::$GAMEMATCH_RESULT_FIRST);
			$oMatch->save();
                        
                        $gm=new Game();
                        $gm->setMatchId($oMatch->getId());
                        $gm->setStatus(Game::$GAME_STATUS_ENDED);
                        //$gm->setSwitches(false);
                        if($data_node->getType()==gameRules::$RT_TREE)
                             $gm->setNode ($this->getGameNode($data_node));
                        $gm->save();
                        
                        $pts=new Score();
                        $pts->setMatchId($oMatch->getId());
                        $pts->setGameId($gm->getId());
                        $pts->setScore($oTournament->getRules()->getFreepts());
                        $pts->save();
                        
			unset($aPlayers[$key]);
		}
		
		for ($i=0; $i<$iPlayersCount/2; $i++)
		{
			$key=array_rand($aPlayers,2);
			
			$aPlayers[$key[0]]->setStatus(ActivPlayer::$ACTION_PLAYING);
                        $aPlayers[$key[0]]->save();
			
			$aPlayers[$key[1]]->setStatus(ActivPlayer::$ACTION_PLAYING);
                        $aPlayers[$key[1]]->save();
			
			$oMatch=new GameMatch();
			$oMatch->setFirstPlayerId($aPlayers[$key[0]]->getId());
			$oMatch->setSecondPlayerId($aPlayers[$key[1]]->getId());
                        $oMatch->setRoundId($iRound);
                        $oMatch->setStatus(GameMatch::$GAMEMATCH_STATUS_START);
			$oMatch->setTournamentId($oTournament->getId());
			$oMatch->save();
			
                        $gm=new Game();
                        $gm->setMatchId($oMatch->getId());
                        $gm->setStatus(Game::$GAME_STATUS_START);
                       // $gm->setSwitches(false);
                        if($data_node->getType()==gameRules::$RT_TREE)
                             $gm->setNode ($this->getGameNode($data_node));
                        $gm->save();
                        
			unset($aPlayers[$key[0]]);
			unset($aPlayers[$key[1]]);
		}		
	}
	
}